>From b05e27ba9b0ba9ef00ad2183933652e08d8c89af Mon Sep 17 00:00:00 2001
From: Stefan Tomanek <stefan@pico.ruhr.de>
Date: Sat, 29 Oct 2011 20:48:55 +0200
Subject: [PATCH] rewrite and modernize POP decoder


Signed-off-by: Stefan Tomanek <stefan@pico.ruhr.de>
---
 decode_pop.c |   96 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 77 insertions(+), 19 deletions(-)
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/

--- a/decode_pop.c
+++ b/decode_pop.c
@@ -6,6 +6,8 @@
  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
  *
  * $Id: decode_pop.c,v 1.4 2001/03/15 08:33:02 dugsong Exp $
+ *
+ * Rewritten by Stefan Tomanek 2011 <stefan@pico.ruhr.de>
  */
 
 #include "config.h"
@@ -45,32 +47,88 @@
 decode_pop(u_char *buf, int len, u_char *obuf, int olen)
 {
 	char *p;
+	char *s;
+	int n;
 	int i, j;
+	char *user;
+	char *password;
+	enum {
+		NONE,
+		AUTHPLAIN,
+		AUTHLOGIN,
+		USERPASS
+	} mode = NONE;
+
 	
 	obuf[0] = '\0';
 	
 	for (p = strtok(buf, "\r\n"); p != NULL; p = strtok(NULL, "\r\n")) {
-		if (strncasecmp(p, "AUTH PLAIN", 10) == 0 ||
-		    strncasecmp(p, "AUTH LOGIN", 10) == 0) {
-			strlcat(obuf, p, olen);
-			strlcat(obuf, "\n", olen);
-			
-			/* Decode SASL auth. */
-			for (i = 0; i < 2 && (p = strtok(NULL, "\r\n")); i++) {
-				strlcat(obuf, p, olen);
-				j = base64_pton(p, p, strlen(p));
-				p[j] = '\0';
-				strlcat(obuf, " [", olen);
-				strlcat(obuf, p, olen);
-				strlcat(obuf, "]\n", olen);
+		if (mode == NONE) {
+			user = NULL;
+			password = NULL;
+			if (strncasecmp(p, "AUTH PLAIN", 10) == 0) {
+				mode = AUTHPLAIN;
+				continue;
+			}
+			if (strncasecmp(p, "AUTH LOGIN", 10) == 0) {
+				mode = AUTHLOGIN;
+				continue;
+			}
+			if (strncasecmp(p, "USER ", 5) == 0) {
+				mode = USERPASS;
+				/* the traditional login cuts right to the case,
+				 * so no continue here
+				 */
 			}
 		}
-		/* Save regular POP2, POP3 auth info. */
-		else if (strncasecmp(p, "USER ", 5) == 0 ||
-			 strncasecmp(p, "PASS ", 5) == 0 ||
-			 strncasecmp(p, "HELO ", 5) == 0) {
-			strlcat(obuf, p, olen);
-			strlcat(obuf, "\n", olen);
+		printf("(%d) %s\n", mode, p);
+		if (mode == USERPASS) {
+			if (strncasecmp(p, "USER ", 5) == 0) {
+				user = &p[5];
+			} else if (strncasecmp(p, "PASS ", 5) == 0) {
+				password = &p[5];
+			}
+		}
+
+		if (mode == AUTHPLAIN) {
+			j = base64_pton(p, p, strlen(p));
+			p[j] = '\0';
+			n = 0;
+			s = p;
+			/* p consists of three parts, divided by \0 */
+			while (s <= &p[j] && n<=3) {
+				if (n == 0) {
+					/* we do not process this portion yet */
+				} else if (n == 1) {
+					user = s;
+				} else if (n == 2) {
+					password = s;
+				}
+				n++;
+				while (*s) s++;
+				s++;
+			}
+		}
+
+		if (mode == AUTHLOGIN) {
+			j = base64_pton(p, p, strlen(p));
+			p[j] = '\0';
+			if (! user) {
+				user = p;
+			} else {
+				password = p;
+				/* got everything we need :-) */
+			}
+		}
+
+		if (user && password) {
+			strlcat(obuf, "\nusername [", olen);
+			strlcat(obuf, user, olen);
+			strlcat(obuf, "] password [", olen);
+			strlcat(obuf, password, olen);
+			strlcat(obuf, "]\n", olen);
+
+			mode = NONE;
 		}
 	}
 	return (strlen(obuf));
